package cn.agiledata.bank.audit.service;

import java.util.Date;

import cn.agiledata.bank.audit.exception.AuditException;
import cn.agiledata.bank.audit.logic.AuditStatus;
import cn.agiledata.bank.hibernateBean.Account;
import cn.agiledata.bank.hibernateBean.AuditOperandType;
import cn.agiledata.bank.hibernateBean.HistoryAuditOperation;
import cn.agiledata.bank.hibernateBean.Operator;
import cn.agiledata.bank.hibernateBean.RecentAuditOperation;
import cn.agiledata.bank.hibernateBean.UserInfo;

/**
 * 对外提供各种审核服务的审核核心接口
 * 
 * @author 马贤波
 * 
 */
public interface AuditService {

    /**
     * 审核同意指定审核对象。采用的审核规则是在该审核对象提交审核时使用的有效审核规则，即使原审核规则已失效
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * @param operator
     *            操作员
     * @param attitude
     *            审核意见
     * @return true if 终审通过审核完毕, otherwise false
     * @throws AuditException
     *             如果审核操作过程中出现错误
     */
    public boolean agree(AuditOperandType auditOperandType,
            long auditOperandId, Operator operator, String attitude)
            throws AuditException;

    /**
     * 审核同意指定审核对象。采用的审核规则是在该审核对象提交审核时使用的有效审核规则，即使原审核规则已失效
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * @param user
     *            后台用户
     * @param attitude
     *            审核意见
     * @return true if 审核完毕, otherwise false
     * @throws AuditException
     *             如果审核操作过程中出现错误
     */
    public boolean agree(AuditOperandType auditOperandType,
            long auditOperandId, UserInfo user, String attitude)
            throws AuditException;

    /**
     * 创建指定审核对象的初始审核数据，在新建并保存一个审核对象后调用
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * @param account
     *            前台用户
     * @throws AuditException
     *             如果审核操作过程中出现错误
     */
    public void create(AuditOperandType auditOperandType, long auditOperandId,
            Account account) throws AuditException;

    /**
     * 创建指定审核对象的初始审核数据，在新建并保存一个审核对象后调用
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * @param operator
     *            操作员
     * @throws AuditException
     *             如果审核操作过程中出现错误
     */
    public void create(AuditOperandType auditOperandType, long auditOperandId,
            Operator operator) throws AuditException;

    /**
     * 创建指定审核对象的初始审核数据，在新建并保存一个审核对象后调用
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * @param user
     *            后台用户
     * @throws AuditException
     *             如果审核操作过程中出现错误
     */
    public void create(AuditOperandType auditOperandType, long auditOperandId,
            UserInfo user) throws AuditException;

    /**
     * 根据类型名和操作类型标志获取AuditOperandType对象
     * 
     * @param className
     *            类型名，可以为完成类名、简单类名或者数据库表名
     * @param actionFlag
     *            操作类型标志
     * @return 表示操作类型的AuditOperandType对象
     */
    public AuditOperandType getAuditOperandType(String className,
            String actionFlag);

    /**
     * 获取指定审核对象的指定审核状态的名称。除了初始状态、退回状态和审核完毕状态，
     * 其它审核状态的名称与指定审核对象使用的审核规则相关，所以必须提供审核对象id
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * @param auditStatus
     *            审核状态
     * 
     * @return 指定审核对象的指定审核状态的名称
     */
    public String getAuditStatusLabel(AuditOperandType auditOperandType,
            long auditOperandId, AuditStatus auditStatus);

    /**
     * 获取指定审核对象的指定审核状态的名称
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * @param auditStatus
     *            审核状态值
     * 
     * @return 指定审核对象的指定审核状态的名称
     */
    public String getAuditStatusLabel(AuditOperandType auditOperandType,
            long auditOperandId, int auditStatus);

    /**
     * 查询指定后台用户具有审核权限的所有审核对象的最近审核操作。 这是一个耗时的方法。
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param user
     *            后台用户
     * @param beginIndex
     *            查询起始位置，为0则不进行分页查询
     * @param maxTotal
     *            查询最大总数，为0则不进行分页查询
     * @return 指定后台用户具有审核权限的所有审核对象的最近审核操作
     */
    public RecentAuditOperation[] getAuthoritativeRecentAuditOperations(
            AuditOperandType auditOperandType, UserInfo user, int beginIndex,
            int maxTotal);

    /**
     * 查询指定前台操作员具有审核权限的所有审核对象的最近审核操作。 这是一个耗时的方法。
     * 
     * @param auditOperandTypes
     *            审核对象类型清单。支持查询多种审核对象类型下的审核对象的最近审核操作
     * @param operator
     *            前台操作员
     * @param beginIndex
     *            查询起始位置，为0则不进行分页查询
     * @param maxTotal
     *            查询最大总数，为0则不进行分页查询
     * @return 指定前台操作员具有审核权限的所有审核对象的最近审核操作
     */
    public RecentAuditOperation[] getAuthoritativeRecentAuditOperations(
            AuditOperandType[] auditOperandTypes, Operator operator,
            int beginIndex, int maxTotal);

    /**
     * 查询指定后台用户具有审核权限的所有审核对象的最近审核操作的总数
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param user
     *            后台用户
     * @return 指定后台用户具有审核权限的所有最近审核操作的总数
     */
    public long getAuthoritativeRecentAuditOperationsTotal(
            AuditOperandType auditOperandType, UserInfo user);

    /**
     * 查询指定前台操作员具有审核权限的所有审核对象的最近审核操作的总数
     * 
     * @param auditOperandTypes
     *            审核对象类型清单。支持查询多种审核对象类型下的审核对象的最近审核操作的总数
     * @param operator
     *            前台操作员
     * @return 指定前台操作员具有审核权限的所有审核对象的最近审核操作的总数
     */
    public long getAuthoritativeRecentAuditOperationsTotal(
            AuditOperandType[] auditOperandTypes, Operator operator);

    /**
     * 获取指定审核对象的当前审核状态
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * 
     * @return 指定审核对象的当前审核状态
     */
    public AuditStatus getCurrentAuditStatus(AuditOperandType auditOperandType,
            long auditOperandId);

    /**
     * 查询指定后台用户在指定审核起始时间和结束时间之间进行的，审核后状态为指定状态的，所有审核操作
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param postStatuses
     *            审核后状态，为空或长度为0则不计入查询条件
     * @param users
     *            后台用户，为空或长度为0则不计入查询条件
     * @param beginAuditTime
     *            审核起始时间，为空则不计入查询条件
     * @param endAuditTime
     *            审核结束时间，为空则不计入查询条件
     * @param beginIndex
     *            查询起始位置，为0则不进行分页查询
     * @param maxTotal
     *            查询最大总数，为0则不进行分页查询
     * @return 指定后台用户在指定审核起始时间和结束时间之间进行的，审核后状态为指定状态的，所有审核操作
     */
    public HistoryAuditOperation[] getHistoryAuditOperations(
            AuditOperandType auditOperandType, AuditStatus[] postStatuses,
            UserInfo[] users, Date beginAuditTime, Date endAuditTime,
            int beginIndex, int maxTotal);

    /**
     * 获取指定审核对象类型的指定审核对象的历史审核操作清单
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * 
     * @return 指定审核对象类型的指定审核对象的历史审核操作清单
     */
    public HistoryAuditOperation[] getHistoryAuditOperations(
            AuditOperandType auditOperandType, long auditOperandId);

    /**
     * 获取指定审核对象类型的，指定审核对象的，最后一轮审核流程中的历史审核操作
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * @return 指定审核对象类型的，指定审核对象的，最后一轮审核流程中的历史审核操作
     */
    public HistoryAuditOperation[] getHistoryAuditOperationsOfLastFlow(
            AuditOperandType auditOperandType, long auditOperandId);

    /**
     * 查询指定后台用户在指定审核起始时间和结束时间之间进行的，审核后状态为指定状态的，所有审核操作的总数
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param postStatuses
     *            审核后状态，为空或长度为0则不计入查询条件
     * @param users
     *            后台用户，为空或长度为0则不计入查询条件
     * @param beginAuditTime
     *            审核起始时间，为空则不计入查询条件
     * @param endAuditTime
     *            审核结束时间，为空则不计入查询条件
     * @return 指定后台用户在指定审核起始时间和结束时间之间进行的，审核后状态为指定状态的，所有审核操作的总数
     */
    public long getHistoryAuditOperationsTotal(
            AuditOperandType auditOperandType, AuditStatus[] postStatuses,
            UserInfo[] users, Date beginAuditTime, Date endAuditTime);

    /**
     * 获取指定审核对象类型的指定审核对象的最近审核操作
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * 
     * @return 指定审核对象类型的指定审核对象的最近审核操作
     */
    public RecentAuditOperation getRecentAuditOperation(
            AuditOperandType auditOperandType, long auditOperandId);

    /**
     * 判断指定操作员对指定审核对象是否具有审核权限
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * @param operator
     *            操作员
     * 
     * @return true if 指定操作员对指定审核对象具有审核权限, otherwise false
     */
    public boolean hasAuditAuthority(AuditOperandType auditOperandType,
            long auditOperandId, Operator operator);

    /**
     * 判断指定操作员对指定审核对象是否具有审核权限
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * @param user
     *            后台用户
     * @return true if 指定操作员对指定审核对象具有审核权限, otherwise false
     */
    public boolean hasAuditAuthority(AuditOperandType auditOperandType,
            long auditOperandId, UserInfo user);

    /**
     * 判断指定审核对象是否已经审核完毕
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * 
     * @return true if 指定审核对象已经审核完毕, otherwise false
     */
    public boolean isFinished(AuditOperandType auditOperandType,
            long auditOperandId);

    /**
     * 判断指定审核对象是否被审核拒绝
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * @return true if 指定审核对象被审核拒绝, otherwise false
     */
    public boolean isRejected(AuditOperandType auditOperandType,
            long auditOperandId);

    /**
     * 审核拒绝指定审核对象
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * @param operator
     *            操作员
     * @param attitude
     *            审核意见
     * @throws AuditException
     *             如果审核操作过程中出现错误
     */
    public void reject(AuditOperandType auditOperandType, long auditOperandId,
            Operator operator, String attitude) throws AuditException;

    /**
     * 审核拒绝指定审核对象
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * @param user
     *            后台用户
     * @param attitude
     *            审核意见
     * @throws AuditException
     */
    public void reject(AuditOperandType auditOperandType, long auditOperandId,
            UserInfo user, String attitude) throws AuditException;

    /**
     * 判断指定审核对象类型是否需要后台系统审核
     * 
     * @param auditOperandType
     *            审核对象类型
     * @return true if 指定审核对象类型需要后台系统审核, otherwise false
     */
    public boolean requiredSystemAudit(AuditOperandType auditOperandType);

    /**
     * 判断指定的审核对象类型是否需要客户审核，若指定审核对象类型为系统审核对象类型，则直接返回false
     * 
     * @param accountId
     *            当前用户的主账户id
     * @param auditOperandType
     *            审核对象类型
     * @return true if 指定的审核对象类型需要客户审核, otherwise false
     */
    public boolean requiredUserAudit(long accountId,
            AuditOperandType auditOperandType);

    /**
     * 前台用户提交指定审核对象，只有审核状态为初始状态或退回状态的审核对象才能被提交审核， 不需要审核的审核对象直接提交至后续流程
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * @param account
     *            前台用户
     * @throws AuditException
     *             如果审核操作过程中出现错误
     */
    public void submit(AuditOperandType auditOperandType, long auditOperandId,
            Account account) throws AuditException;

    /**
     * 操作员提交指定审核对象，只有审核状态为初始状态或退回状态的审核对象才能被提交审核， 不需要审核的审核对象直接提交至后续流程
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * @param operator
     *            操作员
     * @throws AuditException
     *             如果审核操作过程中出现错误
     */
    public void submit(AuditOperandType auditOperandType, long auditOperandId,
            Operator operator) throws AuditException;

    /**
     * 后台用户提交指定审核对象，只有审核状态为初始状态或退回状态的审核对象才能被提交审核， 不需要审核的审核对象直接提交至后续流程
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * @param user
     *            后台用户
     * @throws AuditException
     *             如果审核操作过程中出现错误
     */
    public void submit(AuditOperandType auditOperandType, long auditOperandId,
            UserInfo user) throws AuditException;

    /**
     * 后台用户重置已终审完毕的审核对象到未提交状态，相当于会计销章
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * @param user
     *            后台用户
     * @param attitude
     *            处理意见
     * @throws AuditException
     *             如果审核操作过程中出现错误
     */
    public void reset(AuditOperandType auditOperandType, long auditOperandId,
            UserInfo user, String attitude) throws AuditException;

    /**
     * 后台用户取消已进入审核流程的审核对象，将其审核状态置为已取消
     * 
     * @param auditOperandType
     *            审核对象类型
     * @param auditOperandId
     *            审核对象id
     * @param user
     *            后台用户
     * @param attitude
     *            处理意见
     * @throws AuditException
     *             如果审核操作过程中出现错误
     */
    public void cancel(AuditOperandType auditOperandType, long auditOperandId,
            UserInfo user, String attitude) throws AuditException;
    
    /**
     * 区别公司资料审核
     * @param auditOperandType
     * @param auditOperandId
     * @param account
     * @param auditType
     * @throws AuditException
     */
    public void submit(AuditOperandType auditOperandType, long auditOperandId,
            Account account,boolean auditType) throws AuditException;

}
